package com.novartis.nims.imagedc.application;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import java.text.ParseException;
import java.util.regex.Pattern;

import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import javax.swing.text.MaskFormatter;

import com.novartis.nims.imagedc.logic.ImageResource;
import com.novartis.nims.imagedc.logic.Scan;
import com.novartis.nims.imagedc.util.CheckBoxHeader;
import com.novartis.nims.imagedc.util.DefaultTableHeaderCellRenderer;
import com.novartis.nims.imagedc.util.FormattedEditor;
import com.novartis.nims.imagedc.util.RegexPatternFormatter;
import com.pixelmed.dicom.DicomException;
import com.pixelmed.display.SingleImagePanel;
import com.pixelmed.display.SourceImage;

@SuppressWarnings("serial")
public class ScanReviewPanel extends JPanel {
	
	private JScrollPane scanTableScrollPane;
	private JScrollPane imageViewScrollPane;
	
	private JTable scanTable;
	private ScanTableModel model = null;
	
	private JPanel imageViewPanel;

	public ScanReviewPanel() {
		JLabel instructionLabel = new JLabel("Enter scan identifiers in the table below. You must fill all required fields (highlighted in orange) before continuing.");
		instructionLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
		
		scanTable = new JTable();
		scanTable.setFillsViewportHeight(true);
		scanTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
		
		scanTableScrollPane = new JScrollPane();
		scanTableScrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
		scanTableScrollPane.setViewportView(scanTable);
		scanTableScrollPane.setPreferredSize(new Dimension(0, 275));
		
		imageViewPanel = new JPanel();
		imageViewScrollPane = new JScrollPane();
		imageViewScrollPane.setViewportView(imageViewPanel);
		imageViewScrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
		
		this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		this.add(instructionLabel);
		this.add(Box.createRigidArea(new Dimension(1, 10)));
		this.add(scanTableScrollPane);
		this.add(Box.createRigidArea(new Dimension(1, 10)));
		this.add(imageViewScrollPane);
	}

	void updateTableModel(ScanTableModel theModel) {
		model = theModel;
		
		imageViewPanel.removeAll();
		imageViewPanel.repaint();
		
		scanTable.setModel(model);
		scanTable.getSelectionModel().addListSelectionListener(new ImageDisplaySelectionHandler(model, this));
		scanTable.setRowSorter(new TableRowSorter<ScanTableModel>(model));
		for (ScanTableModel.Column col : ScanTableModel.Column.values()) {
			final Color emptyColor;
			final Color filledColor = Color.WHITE;
			final boolean enabled;

			if (col.getEditState() == ScanTableModel.EditState.REQUIRED) {
				emptyColor = Color.ORANGE;
				enabled = true;
			} else if (col.getEditState() == ScanTableModel.EditState.OPTIONAL) {
				emptyColor = Color.WHITE;
				enabled = true;
			} else if (col.getEditState() == ScanTableModel.EditState.FIXED) {
				emptyColor = Color.WHITE;
				enabled = false;
			} else {
				emptyColor = Color.WHITE;
				enabled = false;
			}
			TableColumn tableColumn = scanTable.getColumn(col.getColumnName());

			if (scanTable.getColumnClass(col.ordinal()).equals(String.class)) {
				tableColumn.setHeaderRenderer(new DefaultTableHeaderCellRenderer() {
					@Override
					public Component getTableCellRendererComponent(JTable table,
							Object value, boolean isSelected, boolean hasFocus,
							int row, int column) {
						Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
								row, column);
						if (enabled) {
							component.setFont(component.getFont().deriveFont(Font.BOLD));
						}

						return component;
					}
				});

				tableColumn.setCellRenderer(new DefaultTableCellRenderer() {
					@Override
					public Component getTableCellRendererComponent(JTable table,
							Object value, boolean isSelected, boolean hasFocus,
							int row, int column) {
						if (model.isRowForSubmission(row)) {
							if (table.getValueAt(row, column) == null || table.getValueAt(row, column).toString().equals("")) {
								setBackground(emptyColor);
							} else {
								setBackground(filledColor);
							}
						} else {
							setBackground(filledColor);
						}
						setEnabled(enabled);
						return super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
								row, column);
					}

				});
			} else if (scanTable.getColumnClass(col.ordinal()).equals(Boolean.class)) {
				final int colIndex = col.ordinal();
				System.out.println(col.ordinal());
				tableColumn.setHeaderRenderer(new CheckBoxHeader(new ItemListener() {
					public void itemStateChanged(ItemEvent e) {
						Object source = e.getSource();
						if (source instanceof AbstractButton == false) return;
						boolean checked = e.getStateChange() == ItemEvent.SELECTED;
						for (int x = 0, y = scanTable.getRowCount(); x < y; x++) {
							scanTable.setValueAt(new Boolean(checked), x, colIndex);
						}
					}
				}, true));
				
				//use default cell renderer; automatically creates checkboxes
			}
		}

		try {
			scanTable.getColumn(ScanTableModel.Column.SITE_SUBJECT_ID.getColumnName()).setCellEditor(new FormattedEditor(new JFormattedTextField(new MaskFormatter("####_#####"))));
			scanTable.getColumn(ScanTableModel.Column.VISIT_NUMBER.getColumnName()).setCellEditor(new FormattedEditor(new JFormattedTextField(new RegexPatternFormatter(Pattern.compile("^[0-9]+$")))));
			scanTable.getColumn(ScanTableModel.Column.VISIT_REPEAT_NUMBER.getColumnName()).setCellEditor(new FormattedEditor(new JFormattedTextField(new RegexPatternFormatter(Pattern.compile("^[0-9]+\\.[0-9]{2}$")))));
			scanTable.getColumn(ScanTableModel.Column.STUDY_ID.getColumnName()).setCellEditor(new FormattedEditor(new JFormattedTextField(new RegexPatternFormatter(Pattern.compile("^(()|(C[A-Z]{3,4}[0-9]{3}(([A-Z]{0,1}[0-9]{4,5})|([A-Z]{3}[0-9]{2}))))$")))));
		} catch (ParseException e) { e.printStackTrace(); }
		
		this.revalidate();
	}
	
	void clearTable() {
		imageViewPanel.removeAll();
		imageViewPanel.repaint();
		
		scanTable.setModel(new DefaultTableModel());
		this.revalidate();
	}
	
	void setScan(Scan scan) {
		imageViewPanel.removeAll();
		imageViewPanel.repaint();
		
		if (scan != null) {
			for (ImageResource imageResource : scan) {
				SourceImage image = null;
				try {
					image = imageResource.getImage();
				} catch (DicomException e) {
					continue;
				} catch (IOException e) {
					continue;
				}
				if (image == null) {
					continue;
				}

				SingleImagePanel iPanel = new SingleImagePanel(image);
				iPanel.setPreferredSize(new Dimension(275, 275));
				imageViewPanel.add(iPanel);
			}
			imageViewScrollPane.setPreferredSize(new Dimension(0, 315));
			imageViewScrollPane.setMaximumSize(new Dimension(Integer.MAX_VALUE, 315));
		}
		
		this.revalidate();
	}
	
	boolean isInputValid() {
		return model.areRequiredCellsFilled();
	}

}